package com.jichangxiu.framework.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.reflect.GenericTypeUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.github.yulichang.base.MPJBaseService;
import com.jichangxiu.common.utils.ConvertUtils;

import java.io.Serializable;
import java.util.Collection;
import java.util.List;
import java.util.Map;

public interface BaseService<T, V> extends MPJBaseService<T> {

    default V voById(Serializable id) {
        return voById(id, this.voClass());
    }

    default <C> C voById(Serializable id, Class<C> voClass) {
        T obj = getBaseMapper().selectById(id);
        if (ObjectUtil.isNull(obj)) return null;
        return ConvertUtils.convert(obj, voClass);
    }

    default V vo(Wrapper<T> wrapper) {
        return vo(wrapper, this.voClass());
    }

    default <C> C vo(Wrapper<T> wrapper, Class<C> voClass) {
        T obj = getBaseMapper().selectOne(wrapper);
        if (ObjectUtil.isNull(obj)) return null;
        return ConvertUtils.convert(obj, voClass);
    }

    default List<T> list() {
        return this.list(new QueryWrapper<>());
    }

    default List<V> voListByIds(Collection<? extends Serializable> idList) {
        return voListByIds(idList, this.voClass());
    }

    default <C> List<C> voListByIds(Collection<? extends Serializable> idList, Class<C> voClass) {
        List<T> list = getBaseMapper().selectBatchIds(idList);
        if (CollUtil.isEmpty(list)) return CollUtil.newArrayList();
        return ConvertUtils.convert(list, voClass);
    }

    default List<V> voList() {
        return voList(new QueryWrapper<>(), this.voClass());
    }

    default List<V> voList(Wrapper<T> wrapper) {
        return voList(wrapper, this.voClass());
    }

    default <C> List<C> voList(Wrapper<T> wrapper, Class<C> voClass) {
        List<T> list = getBaseMapper().selectList(wrapper);
        if (CollUtil.isEmpty(list)) return CollUtil.newArrayList();
        return ConvertUtils.convert(list, voClass);
    }

    default List<V> voMap(Map<String, Object> map) {
        return voMap(map, this.voClass());
    }

    default <C> List<C> voMap(Map<String, Object> map, Class<C> voClass) {
        List<T> list = getBaseMapper().selectByMap(map);
        if (CollUtil.isEmpty(list)) return CollUtil.newArrayList();
        return ConvertUtils.convert(list, voClass);
    }

    default <P extends IPage<V>> P voPage(IPage<T> page, Wrapper<T> wrapper) {
        return voPage(page, wrapper, this.voClass());
    }

    default <C, P extends IPage<C>> P voPage(IPage<T> page, Wrapper<T> wrapper, Class<C> voClass) {
        page = getBaseMapper().selectPage(page, wrapper);
        IPage<C> voPage = new Page<>(page.getCurrent(), page.getSize(), page.getTotal());
        voPage.setRecords(ConvertUtils.convert(page.getRecords(), voClass));
        return (P) voPage;
    }

    default Class<V> voClass() {
        GenericTypeUtils.resolveTypeArguments(this.getClass(), BaseService.class);
        return (Class<V>) GenericTypeUtils.resolveTypeArguments(this.getClass(), BaseService.class)[1];
    }

    default Class<T> poClass() {
        return (Class<T>) GenericTypeUtils.resolveTypeArguments(this.getClass(), BaseService.class)[0];
    }

}
